﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Reflection;
using System.Text;
using smp.QueryDb.Structure;

namespace smp.QueryDb
{
    internal class Map
    {
        private string _columnDeclaration;

        internal Map(PropertyInfo property, Column column)
        {
            Property = property;
            Column = column;
        }

        internal Map(PropertyInfo property, List<Map> nestedMaps)
        {
            Property = property;
            NestedMaps = nestedMaps;
        }

        internal PropertyInfo Property { get; private set; }
        
        internal Column Column { get; private set; }

        internal List<Map> NestedMaps { get; private set; }

        internal void AppendStatementBuilder(ref int index, Table table,  StringBuilder statementBuilder)
        {
            if(Column != null)
            {
                if (!table.IsTableDeclared(Column.TableDeclaration))
                {
                    throw Helper.Error("Invalid map of column {0} to property {1}, table declaraiont {1} not defined in from statement",
                        Column.Name,
                        Property.Name,
                        Column.TableDeclaration);
                }
                _columnDeclaration = string.Format("C{0}", index);
                statementBuilder.AppendFormat(" {0} AS {1},", Column.Declaration, _columnDeclaration);
                index++;
            }

            if(NestedMaps == null)
                return;
            foreach(var nestedMap in NestedMaps)
            {
                nestedMap.AppendStatementBuilder(ref index, table,  statementBuilder);
            }
        }

        internal void PopulateModel(IDataRecord record,  object model)
        {
            object propertyValue;
            if(NestedMaps != null && Column == null)
            {
                propertyValue = Activator.CreateInstance(Property.PropertyType);
                foreach(var map in NestedMaps)
                {
                    map.PopulateModel(record,  propertyValue);
                }
            }
            else
            {
                var recordValue = record[_columnDeclaration];
                if (recordValue == null)
                    return;

                propertyValue = Helper.ConvertType(recordValue, Property.PropertyType);
            }

            
            if (propertyValue == null)
                return;
            Property.SetValue(model, propertyValue, null);
        }
    }
}
